#include "in.h"

struct MemTable *MDBCreateTable( struct MemDatabase *db , char *table_name , size_t record_size )
{
	struct MemTable		*table = NULL ;
	
	int			nret = 0 ;
	
	table = (struct MemTable *)malloc( sizeof(struct MemTable) ) ;
	if( table == NULL )
	{
		tls_last_errno = MDB_ERROR_ALLOC ;
		return NULL;
	}
	memset( table , 0x00 , sizeof(struct MemTable) );
	
	table->table_name_len = strlen(table_name) ;
	if( table->table_name_len >= MDB_TABLE_NAME_MAX_LENGTH )
	{
		tls_last_errno = MDB_ERROR_TABLE_NAME_TOO_LONG ;
		return NULL;
	}
	strcpy( table->table_name , table_name );
	
	table->db = db ;
	
	table->record_size = record_size ;
	table->max_record_no = 0 ;
	
	INIT_LIST_HEAD( & (table->index_list) );
	
	INIT_LIST_HEAD( & (table->record_datapage_list) );
	
	INIT_LIST_HEAD( & (table->uncommit_record_datapage_list) );
	
	nret = AddMemTablesHashNodeDirectly( db , table ) ;
	if( nret )
	{
		free( table );
		return NULL;
	}
	
	table->record_no_index = MDBCreateIndex( table , MDB_RECORD_NO_INDEX_NAME , MDB_UNIQUEINDEX , MDB_RECORD_NO_FIELD_NAME , -sizeof0(struct MemRecordDataUnitHead,record_no) , sizeof0(struct MemRecordDataUnitHead,record_no) , NULL ) ;
	if( table->record_no_index == NULL )
	{
		MDBDropTableDirectly( db , table );
		return NULL;
	}
	
	return table;
}

int MDBDropTable( struct MemDatabase *db , char *table_name )
{
	struct MemTable		*table = NULL ;
	
	table = QueryMemTablesHashNode( db , table_name ) ;
	if( table == NULL )
		return (tls_last_errno=MDB_ERROR_TABLE_NOT_FOUND);	
	
	return MDBDropTableDirectly( db , table ) ;
}

int MDBDropTableDirectly( struct MemDatabase *db , struct MemTable *table )
{
	struct MemIndex		*index = NULL ;
	struct MemIndex		*next_index = NULL ;
	
	list_for_each_entry_safe( index , next_index , & (table->index_list) , struct MemIndex , index_list_node )
	{
		TRACE_PRINTF( "MDBDropIndexDirectly index[%p][%s]\n" , index , index->index_name );
		MDBDropIndexDirectly( table , index );
	}
	
	TRACE_PRINTF( "FreeDataPageDirectly table[%p][%s] record_datapage_list\n" , table , table->table_name );
	FreeDataPageDirectly( & (table->record_datapage_list) );
	
	TRACE_PRINTF( "FreeDataPageDirectly table[%p][%s] uncommit_record_datapage_list\n" , table , table->table_name );
	FreeDataPageDirectly( & (table->uncommit_record_datapage_list) );
	
	TRACE_PRINTF( "RemoveMemTablesHashNodeDirectly table[%p][%s]\n" , table , table->table_name );
	RemoveMemTablesHashNodeDirectly( db , table );
	
	return 0;
}

struct MemTable *MDBQueryTable( struct MemDatabase *db , char *table_name )
{
	return QueryMemTablesHashNode( db , table_name );
}

int MDBSetAutoIncrementField( struct MemTable *table , char *field_name,int field_offset,size_t field_size )
{
	switch( field_size )
	{
		case 1 :
			table->auto_increment_value.uint8 = 0 ;
			break;
		case 2 :
			table->auto_increment_value.uint16 = 0 ;
			break;
		case 4 :
			table->auto_increment_value.uint32 = 0 ;
			break;
		case 8 :
			table->auto_increment_value.uint64 = 0 ;
			break;
		default :
			return (tls_last_errno=MDB_ERROR_AUTOINCREMENT_FIELD_SIZE_INVALID);
	}
	
	table->auto_increment_field.field_name = field_name ;
	table->auto_increment_field.field_offset = field_offset ;
	table->auto_increment_field.field_size = field_size ;
	
	return 0;
}

void SetAutoIncrementFieldValue( struct MemTable *table , char *record_data )
{
	uint8_t		*p_uint8 = NULL ;
	uint16_t	*p_uint16 = NULL ;
	uint32_t	*p_uint32 = NULL ;
	uint64_t	*p_uint64 = NULL ;
	
	switch( table->auto_increment_field.field_size )
	{
		case 1 :
			table->auto_increment_value.uint8++;
			p_uint8 = (uint8_t *)(record_data+table->auto_increment_field.field_offset) ;
			(*p_uint8) = table->auto_increment_value.uint8 ;
			break;
		case 2 :
			table->auto_increment_value.uint16++;
			p_uint16 = (uint16_t *)(record_data+table->auto_increment_field.field_offset) ;
			(*p_uint16) = table->auto_increment_value.uint16 ;
			break;
		case 4 :
			table->auto_increment_value.uint32++;
			p_uint32 = (uint32_t *)(record_data+table->auto_increment_field.field_offset) ;
			(*p_uint32) = table->auto_increment_value.uint32 ;
			break;
		case 8 :
			table->auto_increment_value.uint64++;
			p_uint64 = (uint64_t *)(record_data+table->auto_increment_field.field_offset) ;
			(*p_uint64) = table->auto_increment_value.uint64 ;
			break;
		default :
			tls_last_errno = MDB_ERROR_AUTOINCREMENT_FIELD_SIZE_INVALID ;
			return;
	}
	
	return;
}

